﻿/*
 * Author: Kasper van Voorst
 * */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Diagnostics;

namespace LibraryCS
{
    public class FeatureMatcher
    {
        public FeatureMatcher()
        {

        }

        public int pixelMassCount(byte[] sourceImage, int height, int width)
        {
            int count = 0;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    if (((int)sourceImage[(y * width) + x]) == 0)
                    {
                        count++;
                    }
                }
            }

            return count;
        }
        public Point pixelMassCentroid(byte[] sourceImage, int height, int width)
        {
            int count = 0;
            int yCount = 0;
            int xCount = 0;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    if (((int)sourceImage[(y * width) + x]) == 0)
                    {
                        count++;
                        yCount += y;
                        xCount += x;
                    }
                }
            }

            return new Point(xCount / count, yCount / count);
        }

        public byte[] contouring(byte[] binaryImage, int height, int width)
        {
            byte[] returnImage = (byte[])binaryImage.Clone();
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int location = y * width + x;
                    if ((int)binaryImage[location] == 0)
                    {
                        bool filling = true;
                        for (int q = -1; q < 2; q++)
                        {
                            for (int p = -1; p < 2; p++)
                            {
                                if (x + p < 0 || y + q < 0 || x + p > width - 1 || y + q > height - 1)
                                {
                                    filling = false;
                                    continue;
                                }
                                if ((int)binaryImage[location + (q * width + p)] == 255)
                                {
                                    filling = false;
                                }
                            }
                        }
                        if (filling)
                        {
                            returnImage[location] = 255;
                        }
                    }
                }
            }
            return returnImage;
        }
        public double longestRadius(Point centroid, byte[] sourceImage, int height, int width)
        {
            byte[] contouredImage = contouring(sourceImage, height, width);
            double longest = 0;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    if ((int)contouredImage[y * width + x] == 0)
                    {
                        double length = Math.Sqrt(((Math.Pow(centroid.X - x, 2) + Math.Pow(centroid.Y - y, 2))));
                        if (length > longest)
                        {
                            longest = length;
                        }
                    }
                }
            }
            return longest;
        }

        public int matchTemplate(byte[] compareImage, byte[] inputImage, int compareHeight, int compareWidth, int inputHeight, int inputWidth)
        {
            double massMatch;
            double centroidMatch;
            double radiusMatch;

            massMatch = 100 - ((double)Math.Abs(pixelMassCount(compareImage, compareHeight, compareWidth) - pixelMassCount(inputImage, inputHeight, inputWidth)) 
                                / pixelMassCount(compareImage, compareHeight, compareWidth) * 100);

            Point templateCentroid = pixelMassCentroid(compareImage, compareHeight, compareWidth);
            Point centroid = pixelMassCentroid(inputImage, inputHeight, inputWidth);
            int templateX = templateCentroid.X;
            int templateY = templateCentroid.Y;
            int x = centroid.X;
            int y = centroid.Y;
            double templateRadius = longestRadius(templateCentroid, compareImage, compareHeight, compareWidth);
            double radius = longestRadius(centroid, inputImage, inputHeight, inputWidth);

            double xMatch = 100 - ((double)Math.Abs(templateX - x) / templateX * 100);
            double yMatch = 100 - ((double)Math.Abs(templateY - y) / templateY * 100);

            centroidMatch = (xMatch + yMatch) / 2;

            radiusMatch = 100 - ((double)Math.Abs(templateRadius - radius) / templateRadius) * 100;
            Debug.WriteLine(templateRadius + ", " + radius);
            Debug.WriteLine("" + massMatch + ", " + centroidMatch + ", " + radiusMatch);

            return (int)((massMatch + centroidMatch + radiusMatch) / 3);
        }
    }
}
